package com.ice.framework.web.handler;

import com.alibaba.fastjson.JSON;
import com.ice.framework.web.helper.RequestHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * @author wangwei
 * @Date 2021/12/22 17:57
 */
@ControllerAdvice
public class ResponseBodyAdviceHandler implements ResponseBodyAdvice<Object> {
    private static Logger logger = LoggerFactory.getLogger(ResponseBodyAdviceHandler.class);

    public ResponseBodyAdviceHandler() {
    }

    public boolean supports(MethodParameter methodParamter, Class<? extends HttpMessageConverter<?>> converterType) {
        return this.isRestController(methodParamter) || (isController(methodParamter) && isResponseBody(methodParamter));
    }

    public Object beforeBodyWrite(Object body, MethodParameter methodParamter, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest req, ServerHttpResponse response) {
        HttpServletRequest request = RequestHelper.getRequest();
        if (request == null) {
            return body;
        } else {
            StringBuilder info = (StringBuilder) request.getAttribute("_REQUEST_LOG_INFO_");
            if (info == null) {
                info = new StringBuilder();
            }

            Long startTime = (Long) request.getAttribute("_REQUEST_STARTTIME_");
            info.append("[==响应结果=======]>: ").append(body == null ? "null" : JSON.toJSON(body));
            if (startTime != null) {
                info.append("[==执行耗时=======]>: ").append(System.currentTimeMillis() - startTime).append("ms").append("\n");
            }

            String requestId = (String) request.getAttribute("_REQUEST_ID_");
            logger.info("请求ID:" + requestId + ", 内容：" + info.toString());
            return body;
        }
    }

    private boolean isRestController(MethodParameter methodParamter) {
        RestController annotation = (RestController) methodParamter.getDeclaringClass().getAnnotation(RestController.class);
        return annotation != null;
    }

    private boolean isController(MethodParameter methodParamter) {
        Controller annotation = methodParamter.getDeclaringClass().getAnnotation(Controller.class);
        return annotation != null;
    }

    private boolean isResponseBody(MethodParameter returnType) {
        ResponseBody methodAnnotation = (ResponseBody) returnType.getMethodAnnotation(ResponseBody.class);
        return methodAnnotation != null;
    }
}
